﻿using System;

namespace ExtractItAll.Core
{
  /// <summary>
  /// Defines constants for task status.
  /// </summary>
  public enum TaskStatus
  {
    /// <summary>
    /// Open task ready for execution.
    /// </summary>
    Open,

    /// <summary>
    /// Finished task.
    /// </summary>
    Done,

    /// <summary>
    /// Working on it right now.
    /// </summary>
    Working,

    /// <summary>
    /// Something went wrong with it and not fixable.
    /// </summary>
    Error,

    /// <summary>
    /// Task was stopped and can be executed again (most likely).
    /// </summary>
    Warning
  }

  /// <summary>
  /// A single task.
  /// </summary>
  public class TaskItem
  {
    /// <summary>
    /// Creates a new instance of the <see cref="TaskItem" /> class.
    /// </summary>
    public TaskItem()
    {
      Id = Guid.NewGuid();
      Status = TaskStatus.Open;
      StatusMessage = "";
      Password = "";
      Added = DateTime.Now;
      Finished = DateTime.MinValue;
      TargetPath = "";
    }

    /// <summary>
    /// Gets id.
    /// </summary>
    public Guid Id { get; private set; }

    /// <summary>
    /// Gets or sets status.
    /// </summary>
    public TaskStatus Status { get; set; }

    /// <summary>
    /// Gets or sets status message.
    /// </summary>
    public string StatusMessage { get; set; }

    /// <summary>
    /// Gets or sets full path of archive.
    /// </summary>
    public ArchiveItem Archive { get; set; }

    /// <summary>
    /// Gets or sets the password for the archive
    /// </summary>
    public string Password { get; set; }

    /// <summary>
    /// Gets or sets added timestamp.
    /// </summary>
    public DateTime Added { get; set; }

    /// <summary>
    /// Gets or sets finished timestamp.
    /// </summary>
    public DateTime Finished { get; set; }

    /// <summary>
    /// Gets or sets target path to extract to.
    /// </summary>
    public string TargetPath { get; set; }

    /// <summary>
    /// Gets or sets target path to extract to.
    /// </summary>
    public Type ExtracorType { get; set; }

    /// <summary>
    /// Returns true if the task can be executed.
    /// </summary>
    /// <returns>True if executable, otherwise false.</returns>
    public bool IsExecutable()
    {
      return (Status == TaskStatus.Open);
    }

    /// <summary>
    /// Returns true if the task is finished.
    /// </summary>
    /// <returns>True if finished, otherwise false.</returns>
    public bool IsFinished()
    {
      return (Status == TaskStatus.Done);
    }

    /// <summary>
    /// Returns true if the task is resumeable.
    /// </summary>
    /// <returns>True if the task is resumeable, otherwise false.</returns>
    public bool IsResumeable()
    {
      return (Status == TaskStatus.Warning);
    }

    /// <summary>
    /// Returns true if the task failed.
    /// </summary>
    /// <returns>True if the task failed, otherwise false.</returns>
    public bool IsFailure()
    {
      return (Status == TaskStatus.Error);
    }

    /// <summary>
    /// Returns true if the task is running.
    /// </summary>
    /// <returns>True if the task is running, otherwise false.</returns>
    public bool IsRunning()
    {
      return (Status == TaskStatus.Working);
    }

    /// <summary>
    /// Gets matching method by archive name.
    /// </summary>
    /// <param name="archive">Archive name to look for.</param>
    /// <returns>Matching method.</returns>
    public static Predicate<TaskItem> GetByArchive(string archive)
    {
      return new TaskItemByArchive(archive).Match;
    }

    /// <summary>
    /// Gets matching method by id.
    /// </summary>
    /// <param name="id">Id to look for.</param>
    /// <returns>Matching method.</returns>
    public static Predicate<TaskItem> GetById(Guid id)
    {
      return new TaskItemById(id).Match;
    }

    public void Reset()
    {
      Status = TaskStatus.Open;
      StatusMessage = String.Empty;
      Password = String.Empty;
      Finished = DateTime.MinValue;
    }
  }


  /// <summary>
  /// Provides matching method for archive name.
  /// </summary>
  public class TaskItemByArchive
  {
    private string _Archive;

    /// <summary>
    /// Creates new instance of <see cref="TaskItemByArchive" /> class.
    /// </summary>
    /// <param name="archive">String to compare against.</param>
    public TaskItemByArchive(string archive)
    {
      _Archive = archive;
    }

    /// <summary>
    /// Checks if the passed item matches the condition.
    /// </summary>
    /// <param name="item">Item to check.</param>
    /// <returns>True if matching, otherwise false.</returns>
    public bool Match(TaskItem item)
    {
      return (item.Archive.FileName == _Archive);
    }
  }


  /// <summary>
  /// Provides matching method for id.
  /// </summary>
  public class TaskItemById
  {
    private Guid _Id;

    /// <summary>
    /// Creates new instance of <see cref="TaskItemById" /> class.
    /// </summary>
    /// <param name="id">String to compare against.</param>
    public TaskItemById(Guid id)
    {
      _Id = id;
    }

    /// <summary>
    /// Checks if the passed item matches the condition.
    /// </summary>
    /// <param name="item">Item to check.</param>
    /// <returns>True if matching, otherwise false.</returns>
    public bool Match(TaskItem item)
    {
      return (item.Id == _Id);
    }
  }
}